<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello!</title>
<link rel="stylesheet" href="https://stackedit.io/res-min/themes/base.css" />
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
<style>
body {
  background-color: rgb(253,253,253);
}
</style>
</head>
<body><div class="container"><h1 id="使用-typescript-rect-webpack-编写模块化工程">使用 TypeScript + Rect + WebPack 编写模块化工程</h1>

<ul>
<li>TypeScript 语言规范</li>
<li>Rect、WebPack 介绍</li>
<li>TypeScript + Rect + WebPack 开发示例</li>
</ul>



<h1 id="typescript-语言规范">TypeScript 语言规范</h1>

<blockquote>
  <p>TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source.</p>
</blockquote>

<p>一些 modern language (吸收了 C C++ Lisp Haskell Pascal 等语言的优点，21 世纪之后出现的语言) 的一个功能是把 ECMAScript （JavaScript 语言标准） 作为目标代码。编写非 ECMAScript 代码，通过编译器生成 ECMAScript 代码。</p>



<pre class="prettyprint"><code class="language-? hljs brainfuck"><span class="hljs-literal">+</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">+</span>      <span class="hljs-literal">+</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">+</span>      <span class="hljs-literal">+</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">+</span>
<span class="hljs-comment">|</span> <span class="hljs-comment">lang</span> <span class="hljs-comment">codes</span> <span class="hljs-comment">|</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span>&gt; <span class="hljs-comment">|</span> <span class="hljs-comment">compiler</span> <span class="hljs-comment">|</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span>&gt; <span class="hljs-comment">|</span> <span class="hljs-comment">ECMAScript</span> <span class="hljs-comment">|</span> <span class="hljs-comment">===</span>&gt; <span class="hljs-comment">run</span> <span class="hljs-comment">in</span> <span class="hljs-comment">Browser</span> <span class="hljs-comment">or</span> <span class="hljs-comment">(JS)</span> <span class="hljs-comment">VM</span>
<span class="hljs-literal">+</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">+</span>      <span class="hljs-literal">+</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">+</span>      <span class="hljs-literal">+</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-literal">+</span></code></pre>

<ul>
<li>Nim </li>
<li>Rust</li>
<li>Kotlin</li>
<li>Crystal</li>
<li>TypeScript</li>
<li>…</li>
</ul>

<p>TypeScript 与其他语言不同之处在于：</p>

<ul>
<li>保持和 JavaScript 相同的语法和语义</li>
<li>可以直接使用已有的和将来出现的 JavaScript 代码</li>
<li>提前实现 ECMAScript 2015 （6） 和 ECMASCript 7 规范</li>
<li>微软提供了丰富的工具：vscode 调试器和编辑器</li>
</ul>

<blockquote>
  <p>一些补充</p>
  
  <p>TypeScript 和 JavaScript 这种编译方式不是独有的。GCC 编译 C 代码不是直接生成机器码，而是生成汇编代码，然后借用汇编代码的编译器生成机器码。C++ 早期的目标代码是纯 C 代码。Nim、Kotlin 这两个新出现的语言，也使用了类似的技术。Nim 的目标代码是纯 C，可以和 C 互相调用。Kotlin 的目标代码是 JVM 字节码，可以和 Java 互相调用。</p>
  
  <p>这样做的目的，大多是希望发明新的语言，来提升编程效率、性能，并且保留对旧有代码库的兼容和支持。</p>
</blockquote>



<h2 id="使用-typescript-的好处">使用 TypeScript 的好处</h2>

<ul>
<li>不需要学习新的语法和语义</li>
<li>可以直接使用 JavaScript 库，编写的代码可以为 JavaScript 调用，你仍然可以和不懂 TypeScript 的一起协作</li>
<li>提供静态的类型检查，获得只有静态语言才有的类型安全，并且支持类型推导</li>
<li>模块化，抽象化 — 构建大型工程的基石</li>
<li>提前使用 ECMAScript 2015 （6） 和 ECMASCript 7 规范</li>
</ul>



<h2 id="一个介绍">一个介绍</h2>



<pre class="prettyprint"><code class="language-sh hljs cmake">npm <span class="hljs-keyword">install</span> -g typescript</code></pre>

<p><a href="http://www.typescriptlang.org/play/index.html">Playground online</a></p>



<h2 id="builtin-types">Builtin types</h2>

<ul>
<li><p>number</p>

<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">var</span> a = <span class="hljs-number">1</span>
<span class="hljs-keyword">var</span> b: number = <span class="hljs-number">100</span>
<span class="hljs-keyword">var</span> c = -<span class="hljs-number">1.1</span>

<span class="hljs-keyword">var</span> d: number <span class="hljs-comment">// 声明 （绑定符号 Symbol），分配内存空间</span>
d = <span class="hljs-number">1.1e10</span>    <span class="hljs-comment">// 赋值 （查找符号表，修改符号绑定的内存空间）</span></code></pre></li>
<li><p>string</p>

<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">var</span> a = <span class="hljs-string">"a"</span>
<span class="hljs-keyword">var</span> b: <span class="hljs-keyword">string</span> = <span class="hljs-string">"hello"</span>

<span class="hljs-keyword">var</span> c: <span class="hljs-keyword">string</span>      <span class="hljs-comment">// 声明</span>
c = <span class="hljs-string">"hello world"</span>  <span class="hljs-comment">// 赋值</span></code></pre></li>
<li><p>boolean</p>

<pre class="prettyprint"><code class="language-ts hljs coffeescript"><span class="hljs-reserved">var</span> <span class="hljs-attribute">a</span>: boolean = <span class="hljs-literal">true</span>
<span class="hljs-reserved">var</span> b = <span class="hljs-literal">false</span>

<span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) {
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello world!"</span>)
}</code></pre></li>
<li><p><code>object</code></p>

<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">var</span> a = {name: <span class="hljs-string">"XiaoMing"</span>, age: <span class="hljs-number">21</span>}
<span class="hljs-keyword">typeof</span> a === <span class="hljs-string">"object"</span>

<span class="hljs-keyword">var</span> b = Object.create(<span class="hljs-keyword">null</span>)
b.name = <span class="hljs-string">"Tom"</span>

class Person {
<span class="hljs-keyword">public</span> name: <span class="hljs-keyword">string</span>  
}
<span class="hljs-keyword">var</span> c = <span class="hljs-keyword">new</span> Person()
c.name = <span class="hljs-string">"Lili"</span>
<span class="hljs-keyword">typeof</span> c === <span class="hljs-string">"object"</span></code></pre></li>
<li><p><code>null</code> 和 <code>undefined</code></p>

<p><code>null</code> 和 <code>undefined</code> 是其他任何类型的子类型。但是，通常最好不使用 <code>undefined</code>，除非没有更好的选择。对于 <code>null</code>，当你使用 <code>object</code> 的类型时，当没有赋值的时候，可以选择赋予 <code>null</code> 值。</p>

<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">var</span> a = <span class="hljs-keyword">null</span>
<span class="hljs-keyword">var</span> b: <span class="hljs-keyword">null</span> = <span class="hljs-keyword">null</span>

<span class="hljs-keyword">var</span> c: <span class="hljs-keyword">string</span> = <span class="hljs-keyword">null</span> <span class="hljs-comment">// 声明，赋予 `null`，表示只申请了 c 地址的内存</span>
c = <span class="hljs-string">"abc"</span>            <span class="hljs-comment">// 分配一块内存存储 `abc`，将这个地址赋予 c</span></code></pre></li>
<li><p>void</p>

<pre class="prettyprint"><code class="language-ts hljs actionscript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span><span class="hljs-params">()</span><span class="hljs-type">: void</span> {</span>
console.log(<span class="hljs-number">100</span>)
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">g</span><span class="hljs-params">()</span> {</span>
console.log(<span class="hljs-number">100</span>)
}</code></pre></li>
<li><p>any</p>

<p>忽略类型检查，相当于直接编写 ECMAScript</p>

<pre class="prettyprint"><code class="language-ts hljs livecodeserver">var <span class="hljs-operator">a</span>: <span class="hljs-keyword">any</span> = <span class="hljs-number">100</span>
var c: <span class="hljs-keyword">any</span> = <span class="hljs-string">"abc"</span>
var e: <span class="hljs-keyword">any</span> = {name: <span class="hljs-string">"Tom"</span>}</code></pre></li>
<li><p>Array</p>

<pre class="prettyprint"><code class="language-ts hljs javascript"><span class="hljs-keyword">var</span> a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>]
<span class="hljs-keyword">var</span> b: <span class="hljs-built_in">Array</span>&lt;number&gt; = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]

<span class="hljs-keyword">var</span> c: <span class="hljs-built_in">Array</span>&lt;string&gt; = []
c[<span class="hljs-number">0</span>] = <span class="hljs-string">"hello"</span>
c[<span class="hljs-number">1</span>] = <span class="hljs-string">"world"</span></code></pre></li>
<li><p>tuple</p>

<p>事实上，TypeScript 对于 tuple 的设定非常简陋和粗糙，缺少语义的表示。tuple 是一个数据领域用来表示一个数据项的标准格式。TypeScript 使用一个固定数组表示：</p>

<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">var</span> a = [<span class="hljs-string">"Tom"</span>, <span class="hljs-number">21</span>, <span class="hljs-string">"red"</span>]

<span class="hljs-keyword">var</span> b: [<span class="hljs-keyword">string</span>, number, <span class="hljs-keyword">string</span>]
b = [<span class="hljs-string">"XiaoMing"</span>, <span class="hljs-number">31</span>, <span class="hljs-string">"blue"</span>]</code></pre>

<p>使用范例：</p>

<pre class="prettyprint"><code class="language-ts hljs livecodeserver">var persons: Array&lt;[<span class="hljs-built_in">number</span>, <span class="hljs-keyword">string</span>, <span class="hljs-built_in">number</span>]&gt; = []

persons.push([<span class="hljs-string">"Tom"</span>, <span class="hljs-number">21</span>, <span class="hljs-string">"red"</span>])
persons.push([<span class="hljs-string">"XiaoMing"</span>, <span class="hljs-number">31</span>, <span class="hljs-string">"blue"</span>])
persons.push([<span class="hljs-string">"Lili"</span>, <span class="hljs-number">22</span>, <span class="hljs-string">"yellow"</span>])</code></pre>

<pre class="prettyprint"><code class="language-sql hljs ">+<span class="hljs-comment">------------+-----+------------+</span>
| name       | age | likedColor |
+<span class="hljs-comment">------------+-----+------------+</span>
| "Tom"      | 21  | "red"      |
| "XiaoMing" | 31  | "blue"     |
| "Lili"     | 22  | "yellow"   |
+<span class="hljs-comment">------------+-----+------------+</span></code></pre>

<p>更合格的 tuple 声明（Nim 语言）：</p>

<pre class="prettyprint"><code class="language-nim hljs cs"><span class="hljs-keyword">var</span> a = (<span class="hljs-string">"Tom"</span>, <span class="hljs-number">21</span>, <span class="hljs-string">"red"</span>)
<span class="hljs-keyword">var</span> b: tuple[name: <span class="hljs-keyword">string</span>, age: <span class="hljs-keyword">int</span>, likedColor: <span class="hljs-keyword">string</span>] = (<span class="hljs-string">"XiaoMing"</span>, <span class="hljs-number">31</span>, <span class="hljs-string">"blue"</span>)  </code></pre>

<pre class="prettyprint"><code class="language-nim hljs livecodeserver">type
Person = tuple
  name: <span class="hljs-keyword">string</span>
  age: int
  lokedColor: <span class="hljs-keyword">string</span>

var persons: array[Person, <span class="hljs-number">3</span>] = [] <span class="hljs-comment"># 有 3 个 Person 的数组，体现语义</span>
persons.<span class="hljs-built_in">add</span>((<span class="hljs-string">"Tom"</span>, <span class="hljs-number">21</span>, <span class="hljs-string">"red"</span>))
persons.<span class="hljs-built_in">add</span>((<span class="hljs-string">"XiaoMing"</span>, <span class="hljs-number">31</span>, <span class="hljs-string">"blue"</span>))
persons.<span class="hljs-built_in">add</span>((<span class="hljs-string">"Lili"</span>, <span class="hljs-number">22</span>, <span class="hljs-string">"yellow"</span>))</code></pre>

<blockquote>
  <p>语义的价值：不使用注释，就可以看明白代码的含义。</p>
</blockquote>

<p>tuple unpack （拆包，ECMAScript 2015 规范）：</p>

<pre class="prettyprint"><code class="language-ts hljs makefile">var [a, b, c] = [1, 2, 3]
<span class="hljs-constant">a</span> === 1
<span class="hljs-constant">b</span> === 2
<span class="hljs-constant">c</span> === 3</code></pre></li>
<li><p>enum</p>

<p>枚举，常用在算法表示各个状态：</p>

<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">enum</span> Color {
RED, GREEN, BLUE
}

<span class="hljs-keyword">var</span> a: Color = Color.RED

<span class="hljs-keyword">switch</span> (a) {
<span class="hljs-keyword">case</span> Color.RED:
<span class="hljs-comment">// do something</span>
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">case</span> Color.GREEN:
<span class="hljs-comment">// do something</span>
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">case</span> Color.BLUE:
<span class="hljs-comment">// do something</span>
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">break</span>
}</code></pre></li>
<li><p>class types</p>

<pre class="prettyprint"><code class="language-ts hljs cs">class Person {
<span class="hljs-keyword">public</span> name: <span class="hljs-keyword">string</span>
<span class="hljs-keyword">public</span> age: number
<span class="hljs-keyword">public</span> likedColor: <span class="hljs-keyword">string</span>
<span class="hljs-keyword">protected</span> createDate: Date

<span class="hljs-title">constructor</span>(name: <span class="hljs-keyword">string</span>, age: number, likedColor: <span class="hljs-keyword">string</span>) {
  <span class="hljs-keyword">this</span>.name = name
  <span class="hljs-keyword">this</span>.age = age
  <span class="hljs-keyword">this</span>.likedColor = likedColor
  <span class="hljs-keyword">this</span>.createDate = <span class="hljs-keyword">new</span> Date()
}

<span class="hljs-keyword">public</span> <span class="hljs-title">changeLikedColor</span>(likedColor: <span class="hljs-keyword">string</span>) {
  <span class="hljs-keyword">this</span>.likedColor = likedColor
}

<span class="hljs-keyword">public</span> <span class="hljs-title">print</span>() {
  <span class="hljs-keyword">this</span>.pringLine()
  console.log(<span class="hljs-keyword">this</span>.name + <span class="hljs-string">" age: "</span> + <span class="hljs-keyword">this</span>.age + <span class="hljs-string">" likedColor: "</span> + <span class="hljs-keyword">this</span>.likedColor)
  console.log(<span class="hljs-string">"created at: "</span> + <span class="hljs-keyword">this</span>.createDate.toLocalString())
  <span class="hljs-keyword">this</span>.pringLine()
}

<span class="hljs-keyword">protected</span> <span class="hljs-title">printLine</span>() {
  console.log(<span class="hljs-string">"---------------------------"</span>)
}
}

<span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"XiaoMing"</span>, <span class="hljs-number">31</span>, <span class="hljs-string">"blue"</span>)
person.changeLikedColor(<span class="hljs-string">"cyan"</span>)
person.print()</code></pre>

<pre class="prettyprint"><code class="language-? hljs xml"><span class="hljs-tag">&lt;<span class="hljs-title">hr</span> /&gt;</span>

XiaoMing age: 31 likedColor: cyan
created at: ......
<span class="hljs-tag">&lt;<span class="hljs-title">hr</span> /&gt;</span>
</code></pre></li>
</ul>



<h2 id="class">Class</h2>



<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Person</span><span class="hljs-params">(name, age, likedColor)</span> {</span>
  <span class="hljs-keyword">this</span>.name = name
  <span class="hljs-keyword">this</span>.age = age
  <span class="hljs-keyword">this</span>.likedColor = likedColor
  <span class="hljs-keyword">this</span>.createDate = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
}

Person.prototype.changeLikedColor = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(likedColor)</span> {</span>
  <span class="hljs-keyword">this</span>.likedColor = likedColor
}

Person.prototype.print = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> {</span>
  <span class="hljs-keyword">this</span>.printLine()
  console.log(<span class="hljs-keyword">this</span>.name + <span class="hljs-string">" age: "</span> + <span class="hljs-keyword">this</span>.age + <span class="hljs-string">" likedColor: "</span> + <span class="hljs-keyword">this</span>.likedColor)
  console.log(<span class="hljs-string">"created at: "</span> + <span class="hljs-keyword">this</span>.createDate.toLocalString())
  <span class="hljs-keyword">this</span>.printLine()
}

Person.prototype.printLine = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> {</span>
  console.log(<span class="hljs-string">"---------------------------"</span>)
}</code></pre>

<ul>
<li><p>继承</p>

<p>学生 （也是一个 Person，多了学校） ：</p>

<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Studen</span><span class="hljs-params">(name, age, likedColor, school)</span> {</span>
Person.call(<span class="hljs-keyword">this</span>, name, age, likedColor)
<span class="hljs-keyword">this</span>.school = school
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">F</span><span class="hljs-params">()</span> {</span>
}
F.prototype = Person.prototype
Studen.prototype = <span class="hljs-keyword">new</span> F() 
<span class="hljs-comment">// util.inherits(Person, Studen)</span>

Studen.prototype.print = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> {</span>
Person.prototype.print.call(<span class="hljs-keyword">this</span>)
console.log(<span class="hljs-string">"school: "</span> + <span class="hljs-keyword">this</span>.school)
Person.prototype.print.printLine()
}
</code></pre>

<pre class="prettyprint"><code class="language-? hljs xml"><span class="hljs-tag">&lt;<span class="hljs-title">hr</span> /&gt;</span>

XiaoMing age: 31 likedColor: cyan
created at: ......
<span class="hljs-tag">&lt;<span class="hljs-title">hr</span> /&gt;</span>

school: STF
<span class="hljs-tag">&lt;<span class="hljs-title">hr</span> /&gt;</span>
</code></pre>

<pre class="prettyprint"><code class="language-? hljs 1c">[Person]  &lt;---------+   +--------&gt; [Person.prototype] &lt;---+
name            +-----<span class="hljs-string">|---------   constructor          |</span>
age                   <span class="hljs-string">|            __proto__            |</span>
likedColor            <span class="hljs-string">|            changeLikedColor()   |</span>
created               <span class="hljs-string">|            print()              |</span>
prototype  -----------+            printLine()          <span class="hljs-string">|</span>
__proto__  -&gt; [Function.prototype]                      <span class="hljs-string">|</span>
                                                        <span class="hljs-string">|</span>
                                                        <span class="hljs-string">|</span>
[F]                     +--------&gt; [F.prototype] ---------+
prototype             <span class="hljs-string">|            </span>
__proto__             <span class="hljs-string">|            </span>
                      <span class="hljs-string">|</span>
                      <span class="hljs-string">| </span>
[new F()]               <span class="hljs-string">|</span>
__proto__  -----------+
^
<span class="hljs-string">|</span>
+------------------------------------------------------+
                                                     <span class="hljs-string">|                                                                                                   |</span>
                                                     <span class="hljs-string">|</span>
[Studen]                +--------&gt; [Studen.prototype] -+
school                <span class="hljs-string">|            constructor</span>
prototype  -----------+            __proto__ -&gt; [Object.prototype]
__proto__             <span class="hljs-string">|            print()</span>
                      <span class="hljs-string">|            </span>
                      <span class="hljs-string">|</span>
[new Studen()]          <span class="hljs-string">|</span>
school                <span class="hljs-string">| </span>
__proto__  -----------+</code></pre>

<pre class="prettyprint"><code class="language-ts hljs axapta"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Studen</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Person</span> {</span>
<span class="hljs-keyword">private</span> school: string

constructor(name: string, age: number, likedColor: string, school: string) {
  <span class="hljs-keyword">super</span>(name, age, likedColor)
  <span class="hljs-keyword">this</span>.school = school
}

<span class="hljs-keyword">public</span> print() {
  <span class="hljs-keyword">super</span>.print()
  console.log(<span class="hljs-string">"school: "</span> + <span class="hljs-keyword">this</span>.school)
  <span class="hljs-keyword">this</span>.printLine()
}
}</code></pre></li>
<li><p>abstract class</p>

<p>抽象类用于放置共同方法和数据（不能使用 new 实例化）：</p>

<pre class="prettyprint"><code class="language-ts hljs php"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> {</span>
<span class="hljs-keyword">public</span> x: number
<span class="hljs-keyword">public</span> y: number
<span class="hljs-keyword">public</span> color: string

<span class="hljs-keyword">public</span> draw(ctx) {
  ctx.draw(this.x, this.y, <span class="hljs-number">100</span>, <span class="hljs-number">100</span>, this.color)
}

<span class="hljs-keyword">abstract</span> <span class="hljs-keyword">print</span>(): void
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rect</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> {</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">print</span>() {
  console.log(<span class="hljs-string">"A Rect"</span>)
}
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Line</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> {</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">print</span>() {
  console.log(<span class="hljs-string">"A Line"</span>)
}
}

<span class="hljs-keyword">var</span> rect = <span class="hljs-keyword">new</span> Rect()
rect.draw()
rect.<span class="hljs-keyword">print</span>()

<span class="hljs-keyword">var</span> line = <span class="hljs-keyword">new</span> Line()
line.draw()
line.<span class="hljs-keyword">print</span>()</code></pre></li>
</ul>



<h2 id="interface">Interface</h2>

<p>Interface 常常用在纯面向对象语言，解决纯面向对象语言不支持 Function 但是多态的问题。考虑以下绘图场景：</p>



<pre class="prettyprint"><code class="language-ts hljs cs">class Rect {
  <span class="hljs-keyword">public</span> x: number
  <span class="hljs-keyword">public</span> y: number
  <span class="hljs-keyword">public</span> w: number
  <span class="hljs-keyword">public</span> h: number

  <span class="hljs-title">constructor</span>(x: number, y: number, w: number, h: number) {
    <span class="hljs-keyword">this</span>.x = x
    <span class="hljs-keyword">this</span>.y = y
    <span class="hljs-keyword">this</span>.w = w
    <span class="hljs-keyword">this</span>.h = h
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">draw</span>(ctx) {
    ctx.rect(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y, <span class="hljs-keyword">this</span>.w, <span class="hljs-keyword">this</span>.h)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">print</span>() {
    console.log(<span class="hljs-string">"A Rect"</span>)
  }
}

class Circle {
  <span class="hljs-keyword">public</span> x: number
  <span class="hljs-keyword">public</span> y: number
  <span class="hljs-keyword">public</span> r: number

  <span class="hljs-title">constructor</span>(x: number, y: number, r: number) {
    <span class="hljs-keyword">this</span>.x = x
    <span class="hljs-keyword">this</span>.y = y
    <span class="hljs-keyword">this</span>.r = r
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">draw</span>(ctx) {
    ctx.arc(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y, <span class="hljs-keyword">this</span>.r)
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">print</span>() {
    console.log(<span class="hljs-string">"A shape"</span>)
  }
}

class Container {
  <span class="hljs-keyword">private</span> shapes: Array&lt;?&gt;
  <span class="hljs-keyword">private</span> ctx: Canvas2DCtx

  <span class="hljs-title">constructor</span>() {
    <span class="hljs-keyword">this</span>.ctx = ...
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">add</span>(shape: ?) {

  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">draw</span>() {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> shape of <span class="hljs-keyword">this</span>.shapes) {
      ?
    }
  }
}

<span class="hljs-keyword">var</span> container = <span class="hljs-keyword">new</span> Container()
container.add(<span class="hljs-keyword">new</span> Rect(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">100</span>,<span class="hljs-number">100</span>))
container.add(<span class="hljs-keyword">new</span> Circle(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>,<span class="hljs-number">100</span>))
container.draw()</code></pre>

<p>Interface 作为一个通用方法容器的声明：</p>



<pre class="prettyprint"><code class="language-ts hljs axapta"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> {</span>
  draw(ctx): <span class="hljs-keyword">void</span>
  print(): <span class="hljs-keyword">void</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rect</span> <span class="hljs-inheritance"><span class="hljs-keyword">implements</span></span> <span class="hljs-title">Shape</span> {</span>
  <span class="hljs-keyword">public</span> x: number
  <span class="hljs-keyword">public</span> y: number
  <span class="hljs-keyword">public</span> w: number
  <span class="hljs-keyword">public</span> h: number

  constructor(x: number, y: number, w: number, h: number) {
    <span class="hljs-keyword">this</span>.x = x
    <span class="hljs-keyword">this</span>.y = y
    <span class="hljs-keyword">this</span>.w = w
    <span class="hljs-keyword">this</span>.h = h
  }

  <span class="hljs-keyword">public</span> draw(ctx) {
    ctx.rect(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y, <span class="hljs-keyword">this</span>.w, <span class="hljs-keyword">this</span>.h)
  }

  <span class="hljs-keyword">public</span> print() {
    console.log(<span class="hljs-string">"A Rect"</span>)
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-inheritance"><span class="hljs-keyword">implements</span></span> <span class="hljs-title">Shape</span> {</span>
  <span class="hljs-keyword">public</span> x: number
  <span class="hljs-keyword">public</span> y: number
  <span class="hljs-keyword">public</span> r: number

  constructor(x: number, y: number, r: number) {
    <span class="hljs-keyword">this</span>.x = x
    <span class="hljs-keyword">this</span>.y = y
    <span class="hljs-keyword">this</span>.r = r
  }

  <span class="hljs-keyword">public</span> draw(ctx) {
    ctx.arc(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y, <span class="hljs-keyword">this</span>.r)
  }

  <span class="hljs-keyword">public</span> print() {
    console.log(<span class="hljs-string">"A shape"</span>)
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Container</span> {</span>
  <span class="hljs-keyword">private</span> shapes: Array&lt;Shape&gt;
  <span class="hljs-keyword">private</span> ctx: Canvas2DCtx

  constructor() {
    <span class="hljs-keyword">this</span>.shapes = []
    <span class="hljs-keyword">this</span>.ctx = ...
  }

  <span class="hljs-keyword">public</span> add(shape: Shape) {
    <span class="hljs-keyword">this</span>.shapes.push(shape)
  }

  <span class="hljs-keyword">public</span> draw() {
    <span class="hljs-keyword">for</span> (var shape of <span class="hljs-keyword">this</span>.shapes) {
      shape.print()
      shape.draw(<span class="hljs-keyword">this</span>.ctx)
    }
  }
}

var <span class="hljs-keyword">container</span> = <span class="hljs-keyword">new</span> Container()
<span class="hljs-keyword">container</span>.add(<span class="hljs-keyword">new</span> Rect(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">100</span>,<span class="hljs-number">100</span>))
<span class="hljs-keyword">container</span>.add(<span class="hljs-keyword">new</span> Circle(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>,<span class="hljs-number">100</span>))
<span class="hljs-keyword">container</span>.draw()</code></pre>

<p>用 <code>abstract</code> 可以达到同样效果：</p>



<pre class="prettyprint"><code class="language-ts hljs axapta"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> {</span>
  <span class="hljs-keyword">abstract</span> draw(ctx): <span class="hljs-keyword">void</span>
  <span class="hljs-keyword">abstract</span> print(): <span class="hljs-keyword">void</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rect</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Shape</span> {</span>
  <span class="hljs-keyword">public</span> x: number
  <span class="hljs-keyword">public</span> y: number
  <span class="hljs-keyword">public</span> w: number
  <span class="hljs-keyword">public</span> h: number

  constructor(x: number, y: number, w: number, h: number) {
    <span class="hljs-keyword">this</span>.x = x
    <span class="hljs-keyword">this</span>.y = y
    <span class="hljs-keyword">this</span>.w = w
    <span class="hljs-keyword">this</span>.h = h
  }

  <span class="hljs-keyword">public</span> draw(ctx) {
    ctx.rect(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y, <span class="hljs-keyword">this</span>.w, <span class="hljs-keyword">this</span>.h)
  }

  <span class="hljs-keyword">public</span> print() {
    console.log(<span class="hljs-string">"A Rect"</span>)
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-inheritance"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">Shape</span> {</span>
  <span class="hljs-keyword">public</span> x: number
  <span class="hljs-keyword">public</span> y: number
  <span class="hljs-keyword">public</span> r: number

  constructor(x: number, y: number, r: number) {
    <span class="hljs-keyword">this</span>.x = x
    <span class="hljs-keyword">this</span>.y = y
    <span class="hljs-keyword">this</span>.r = r
  }

  <span class="hljs-keyword">public</span> draw(ctx) {
    ctx.arc(<span class="hljs-keyword">this</span>.x, <span class="hljs-keyword">this</span>.y, <span class="hljs-keyword">this</span>.r)
  }

  <span class="hljs-keyword">public</span> print() {
    console.log(<span class="hljs-string">"A shape"</span>)
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Container</span> {</span>
  <span class="hljs-keyword">private</span> shapes: Array&lt;Shape&gt;
  <span class="hljs-keyword">private</span> ctx: Canvas2DCtx

  constructor() {
    <span class="hljs-keyword">this</span>.shapes = []
    <span class="hljs-keyword">this</span>.ctx = ...
  }

  <span class="hljs-keyword">public</span> add(shape: Shape) {
    <span class="hljs-keyword">this</span>.shapes.push(shape)
  }

  <span class="hljs-keyword">public</span> draw() {
    <span class="hljs-keyword">for</span> (var shape of <span class="hljs-keyword">this</span>.shapes) {
      shape.print()        <span class="hljs-comment">// 多态应用场景</span>
      shape.draw(<span class="hljs-keyword">this</span>.ctx) <span class="hljs-comment">// 多态应用场景</span>
    }
  }
}

var <span class="hljs-keyword">container</span> = <span class="hljs-keyword">new</span> Container()
<span class="hljs-keyword">container</span>.add(<span class="hljs-keyword">new</span> Rect(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">100</span>,<span class="hljs-number">100</span>))
<span class="hljs-keyword">container</span>.add(<span class="hljs-keyword">new</span> Circle(<span class="hljs-number">100</span>,<span class="hljs-number">100</span>,<span class="hljs-number">100</span>))
<span class="hljs-keyword">container</span>.draw()</code></pre>

<p>区别在于 <code>abstract class</code> 不能多继承：</p>



<pre class="prettyprint"><code class="language-ts hljs scala"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rect</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span>, <span class="hljs-title">Board</span></span></code></pre>

<p><code>interface</code> 允许多继承：</p>



<pre class="prettyprint"><code class="language-ts hljs php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rect</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span>, <span class="hljs-title">Board</span></span></code></pre>

<p>正如开头所说的，<code>interface</code> 最开始用于纯面向对象语言（不支持 Function）。所以有其设计的局限和问题，对于 TypeScript 这种支持 Function 的语言，应该尽量减少对 <code>interface</code> 的使用，使用 <code>abstract class</code>。对于多态（比如形状，可能有方形、圆形、三角形，而你想要在一个平面上把它们依次绘制出来。你想要一个数组或者表把它们存储起来），尽可能使用 Function 或者泛型来解决。</p>

<p><code>abstract class</code> 通常能表示一个放置公共数据和方法的地方，而 <code>interface</code> 则没有任何语义，仅仅是为了应对语言的类型兼容。过度使用 <code>interface</code> 只会使得代码拧在一块，业界对于面向对象的批评多来与此（以及类继承）。</p>



<h2 id="generic">Generic</h2>

<p>一个（非循环）双向链表的例子：</p>



<pre class="prettyprint"><code class="language-? hljs smalltalk">   +-----+   +-----+   +-----+   +-----+   +-----+   +-----+
&lt;-&gt;<span class="hljs-localvars">|node1|</span>&lt;-&gt;<span class="hljs-localvars">|node2|</span>&lt;-&gt;<span class="hljs-localvars">|node3|</span>&lt;-&gt;<span class="hljs-localvars">|node4|</span>&lt;-&gt;<span class="hljs-localvars">|node5|</span>&lt;-&gt;<span class="hljs-localvars">|node6|</span>&lt;-&gt;
   |-----|   |-----|   |-----|   |-----|   |-----|   |-----|   
   <span class="hljs-localvars">|value|</span>   <span class="hljs-localvars">|value|</span>   <span class="hljs-localvars">|value|</span>   <span class="hljs-localvars">|value|</span>   <span class="hljs-localvars">|value|</span>   <span class="hljs-localvars">|value|</span>   
   +-----+   +-----+   +-----+   +-----+   +-----+   +-----+</code></pre>



<pre class="prettyprint"><code class="language-ts hljs cs">class Node&lt;T&gt; {
  <span class="hljs-keyword">public</span> next: Node&lt;T&gt; 
  <span class="hljs-keyword">public</span> prev: Node&lt;T&gt;
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">value</span>: T

  <span class="hljs-title">constructor</span>(<span class="hljs-keyword">value</span>: T) {
    <span class="hljs-keyword">this</span>.next = <span class="hljs-keyword">null</span>
    <span class="hljs-keyword">this</span>.prev = <span class="hljs-keyword">null</span>
    <span class="hljs-keyword">this</span>.<span class="hljs-keyword">value</span> = <span class="hljs-keyword">value</span>
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">add</span>(node: Node&lt;T&gt;) {
  <span class="hljs-comment">/*
    prev&lt;-[this]-&gt;next    

    null&lt;-[node]-&gt;null
  */</span>

    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.next === <span class="hljs-keyword">null</span>) {
      <span class="hljs-keyword">this</span>.next = node
      node.prev = <span class="hljs-keyword">this</span>
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">this</span>.next.prev = node
      node.next = <span class="hljs-keyword">this</span>.next
      node.prev = <span class="hljs-keyword">this</span>
      <span class="hljs-keyword">this</span>.next = node
    }
  }

  <span class="hljs-keyword">public</span> <span class="hljs-title">del</span>() {
  <span class="hljs-comment">/*
    prev&lt;-[this]-&gt;next   
  */</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.prev !== <span class="hljs-keyword">null</span>) {
      <span class="hljs-keyword">this</span>.prev.next = <span class="hljs-keyword">this</span>.next
      <span class="hljs-keyword">this</span>.prev = <span class="hljs-keyword">null</span>
    }
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.next !== <span class="hljs-keyword">null</span>) {
      <span class="hljs-keyword">this</span>.next.prev = <span class="hljs-keyword">this</span>.prev
      <span class="hljs-keyword">this</span>.next = <span class="hljs-keyword">null</span>
    }
  }
}

<span class="hljs-keyword">interface</span> Rect {
  x: number
  y: number
  w: number
  h: number
}

<span class="hljs-keyword">var</span> node1 = <span class="hljs-keyword">new</span> Node&lt;Rect&gt;({
  x: <span class="hljs-number">100</span>, y: <span class="hljs-number">100</span>, w: <span class="hljs-number">100</span>, h: <span class="hljs-number">100</span>
})

<span class="hljs-keyword">var</span> node2 = <span class="hljs-keyword">new</span> Node&lt;Rect&gt;({
  x: <span class="hljs-number">200</span>, y: <span class="hljs-number">200</span>, w: <span class="hljs-number">100</span>, h: <span class="hljs-number">100</span>
})

node1.add(node2)

<span class="hljs-keyword">var</span> node3 = <span class="hljs-keyword">new</span> Node&lt;Rect&gt;({
  x: <span class="hljs-number">300</span>, y: <span class="hljs-number">300</span>, w: <span class="hljs-number">100</span>, h: <span class="hljs-number">100</span>
})
node2.add(node3)
<span class="hljs-comment">// &lt;-&gt;node1&lt;-&gt;node2&lt;-&gt;node3</span>

<span class="hljs-keyword">var</span> node = node1
<span class="hljs-keyword">while</span> (node !== <span class="hljs-keyword">null</span>) {
  <span class="hljs-keyword">var</span> rect = node.<span class="hljs-keyword">value</span>
  alert(`${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}`)
  node = node.next
}

alert(<span class="hljs-string">'del node2'</span>)
node2.del()
<span class="hljs-comment">// &lt;-&gt;node1&lt;-&gt;node3</span>

<span class="hljs-keyword">var</span> node = node1
<span class="hljs-keyword">while</span> (node !== <span class="hljs-keyword">null</span>) {
  <span class="hljs-keyword">var</span> rect = node.<span class="hljs-keyword">value</span>
  alert(`${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}`)
  node = node.next
}</code></pre>



<pre class="prettyprint"><code class="language-ts hljs livecodeserver">var <span class="hljs-operator">a</span>: Array&lt;<span class="hljs-built_in">number</span>&gt; = []
<span class="hljs-operator">a</span>.push(<span class="hljs-number">100</span>)
<span class="hljs-operator">a</span>.push(<span class="hljs-number">200</span>)
<span class="hljs-operator">a</span>.push(<span class="hljs-number">300</span>)

var b: Array&lt;<span class="hljs-keyword">string</span>&gt; = []
b.push(<span class="hljs-string">'a'</span>)
b.push(<span class="hljs-string">'b'</span>)
b.push(<span class="hljs-string">'c'</span>)

var c: Array&lt;{name: <span class="hljs-keyword">string</span>, age: <span class="hljs-built_in">number</span>}&gt; = []
c.push({
  name: <span class="hljs-string">'XiaoMing'</span>,
  aget: <span class="hljs-number">31</span>
})
c.push({
  name: <span class="hljs-string">'Tom'</span>,
  age: <span class="hljs-number">21</span>
})</code></pre>



<pre class="prettyprint"><code class="language-ts hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span>&lt;<span class="hljs-title">T</span>: <span class="hljs-title">number</span>|<span class="hljs-title">string</span>&gt;<span class="hljs-params">(x: T)</span> {</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> x === <span class="hljs-string">'number'</span>) {
    console.log(<span class="hljs-string">"x is number"</span>)
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> x === <span class="hljs-string">'string'</span>) {
    console.log(<span class="hljs-string">"x is string"</span>)
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"invalid type"</span>)
  }
} 

f(<span class="hljs-number">1</span>)        <span class="hljs-comment">// x is number</span>
f(<span class="hljs-string">"hello"</span>)  <span class="hljs-comment">// x is string</span>
f(<span class="hljs-literal">null</span>)     <span class="hljs-comment">// Error: invalid type</span></code></pre>

<p>泛型可以帮助你正确的编程，使你避免错误，并且利于代码维护</p>



<h2 id="iterators-and-generators">Iterators and Generators</h2>

<p>(inline) 迭代器就是循环的抽象，避免局部变量无意被修改</p>



<pre class="prettyprint"><code class="language-ts hljs javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> * <span class="hljs-title">f</span><span class="hljs-params">()</span> {</span>
  <span class="hljs-keyword">yield</span> <span class="hljs-number">100</span>
  <span class="hljs-keyword">yield</span> <span class="hljs-number">200</span>
}

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> v of f()) {
  console.log(v)       <span class="hljs-comment">// 100 200  </span>
}</code></pre>



<pre class="prettyprint"><code class="language-ts hljs livecodeserver"><span class="hljs-function"><span class="hljs-keyword">function</span> * <span class="hljs-title">f</span>(<span class="hljs-title">x</span>: <span class="hljs-title">Array</span>&lt;<span class="hljs-title">number</span>&gt;) {</span>
  <span class="hljs-keyword">for</span> (var i = <span class="hljs-number">0</span>, <span class="hljs-built_in">len</span> = x.<span class="hljs-built_in">length</span>; i &lt; <span class="hljs-built_in">len</span>; i++) {
    <span class="hljs-keyword">if</span> (x[i] % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>) {
      yield x[i]
    }
  }
}

<span class="hljs-keyword">for</span> (var <span class="hljs-operator">a</span> <span class="hljs-operator">of</span> [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>]) {
  console.<span class="hljs-built_in">log</span>(<span class="hljs-operator">a</span>)     <span class="hljs-comment"> // 2 4 6</span>
}</code></pre>



<pre class="prettyprint"><code class="language-ts hljs cs"><span class="hljs-keyword">var</span> node = node1
<span class="hljs-keyword">while</span> (node !== <span class="hljs-keyword">null</span>) {
  <span class="hljs-keyword">var</span> rect = node.<span class="hljs-keyword">value</span>
  alert(`${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}`)
  node = node.next
}

function * eachNode&lt;T&gt;(firstNode: Node&lt;T&gt;): Iterable&lt;Node&lt;T&gt;&gt; {
  <span class="hljs-keyword">var</span> node = firstNode
  <span class="hljs-keyword">while</span> (node !== <span class="hljs-keyword">null</span>) {
    <span class="hljs-keyword">yield</span> node
    node = node.next
  }
}

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> node of eachNode(node1)) {
  <span class="hljs-keyword">var</span> rect = node.<span class="hljs-keyword">value</span>
  alert(`${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}`)
}

class Node&lt;T&gt; {
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">public</span> * <span class="hljs-title">eachNode</span>(): Iterable&lt;Node&lt;T&gt;&gt; {
    <span class="hljs-keyword">var</span> node = <span class="hljs-keyword">this</span>
    <span class="hljs-keyword">while</span> (node !== <span class="hljs-keyword">null</span>) {
      <span class="hljs-keyword">yield</span> node
      node = node.next
    }
  }
}

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> node of node1.eachNode()) {
  <span class="hljs-keyword">var</span> rect = node.<span class="hljs-keyword">value</span>
  alert(`${rect.x}, ${rect.y}, ${rect.w}, ${rect.h}`)
}</code></pre>

<p>还有一种使用方法叫做 (closure) 迭代器 — 协程的底层机制：</p>



<pre class="prettyprint"><code class="language-ts hljs cs">function* f(x: Array&lt;number&gt;) {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, len = x.length; i &lt; len; i++) {
    <span class="hljs-keyword">if</span> (x[i] % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">yield</span> x[i]
    }
  }
}

<span class="hljs-keyword">var</span> arr = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>]
<span class="hljs-keyword">var</span> g = f(arr)

<span class="hljs-keyword">var</span> ret = g.next()
ret.<span class="hljs-keyword">value</span> === <span class="hljs-number">2</span>
ret.finish === <span class="hljs-keyword">false</span>

console.log(<span class="hljs-string">'hello'</span>)

<span class="hljs-keyword">var</span> ret = g.next()
ret.<span class="hljs-keyword">value</span> === <span class="hljs-number">4</span>
ret.finish === <span class="hljs-keyword">false</span>

console.log(<span class="hljs-string">'hello'</span>)

<span class="hljs-keyword">var</span> ret = g.next()
ret.<span class="hljs-keyword">value</span> === <span class="hljs-number">6</span>
ret.finish === <span class="hljs-keyword">false</span>

console.log(<span class="hljs-string">'hello'</span>)

<span class="hljs-keyword">var</span> ret = g.next()
ret.finish === <span class="hljs-keyword">true</span></code></pre>



<h2 id="promise-and-async-await">Promise and async await</h2>

<p>例子</p>

<p><a href="">source codes</a></p>

<p><code>async</code> <code>await</code> 是 <code>yield</code> 的语法糖 — 一个预处理器。虚拟机编译成字节码之前对其进行翻译处理。</p>

<p>Go-lang:</p>



<pre class="prettyprint"><code class="language-go hljs "><span class="hljs-keyword">go</span> <span class="hljs-keyword">func</span>() {
  time.Sleep<span class="hljs-number">(1e9</span>)
  timeout &lt;- <span class="hljs-constant">true</span>
}()

<span class="hljs-keyword">switch</span> {
  <span class="hljs-keyword">case</span> &lt;- ch:
    <span class="hljs-comment">// 从ch中读取到数据</span>

  <span class="hljs-keyword">case</span> &lt;- timeout:
    <span class="hljs-comment">// 没有从ch中读取到数据，但从timeout中读取到了数据</span>
}</code></pre>

<p>C#</p>



<pre class="prettyprint"><code class="language-c# hljs cs">class Program {
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">void</span> AsyncMethod() {
    Console.WriteLine(<span class="hljs-string">"开始异步代码"</span>);
    <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> MyMethod();
    Console.WriteLine(<span class="hljs-string">"异步代码执行完毕"</span>);
  }

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">int</span>&gt; MyMethod() {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; i++) {
      Console.WriteLine(<span class="hljs-string">"异步执行"</span> + i.ToString() + <span class="hljs-string">".."</span>);
      <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1000</span>); <span class="hljs-comment">//模拟耗时操作</span>
    }
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
  }

  <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> Main(<span class="hljs-keyword">string</span>[] args) {
    AsyncMethod();
    Thread.Sleep(<span class="hljs-number">1000</span>);
    Console.ReadLine();
  }
}</code></pre>

<p>Nim-lang</p>



<pre class="prettyprint"><code class="language-nim hljs axapta">proc processMessages(<span class="hljs-keyword">server</span>: Server, <span class="hljs-keyword">client</span>: Client) {.async.} =
  <span class="hljs-keyword">while</span> <span class="hljs-keyword">true</span>:
    let line = await <span class="hljs-keyword">client</span>.socket.recvLine()
    await sleepAsync(<span class="hljs-number">1000</span>)
    echo(<span class="hljs-keyword">client</span>, <span class="hljs-string">" sent: "</span>, line)
    <span class="hljs-keyword">for</span> c in <span class="hljs-keyword">server</span>.clients:
      <span class="hljs-keyword">if</span> c.id != <span class="hljs-keyword">client</span>.id:
        await c.socket.send(line)

waitFor <span class="hljs-keyword">server</span>.processMessages(<span class="hljs-keyword">client</span>)</code></pre>

<p>Crystal</p>



<pre class="prettyprint"><code class="language-crystal hljs livecodeserver">def worker(&amp;block)
  <span class="hljs-built_in">result</span> = UnbufferedChannel(Exception?).<span class="hljs-built_in">new</span>

  ::spawn <span class="hljs-built_in">do</span>
    begin
      yield
    rescue ex
      <span class="hljs-built_in">result</span>.<span class="hljs-built_in">send</span>(ex)
    <span class="hljs-keyword">else</span>
      <span class="hljs-built_in">result</span>.<span class="hljs-built_in">send</span>(nil)
    <span class="hljs-function"><span class="hljs-keyword">end</span></span>
  <span class="hljs-function"><span class="hljs-keyword">end</span></span>

  <span class="hljs-built_in">result</span>
<span class="hljs-function"><span class="hljs-keyword">end</span></span>

def pool(size, &amp;block)
  counter = <span class="hljs-number">0</span>
  results = [] <span class="hljs-operator">of</span> UnbufferedChannel(Exception?).<span class="hljs-built_in">new</span>

  loop <span class="hljs-built_in">do</span>
    counter += <span class="hljs-number">1</span>

    <span class="hljs-keyword">while</span> counter &lt; size
      results &lt;&lt; worker { yield }
    <span class="hljs-function"><span class="hljs-keyword">end</span></span>

    <span class="hljs-built_in">result</span> = Channel.select(*results)
    <span class="hljs-keyword">if</span> ex = <span class="hljs-built_in">result</span>.receive
      puts <span class="hljs-string">"ERROR: #{ex.message}\n#{ex.backtrace.join("</span>\n<span class="hljs-string">")}"</span>
      counter -= <span class="hljs-number">1</span>
      results.<span class="hljs-built_in">delete</span>(<span class="hljs-built_in">result</span>)
    <span class="hljs-function"><span class="hljs-keyword">end</span></span>
  <span class="hljs-function"><span class="hljs-keyword">end</span></span>
<span class="hljs-function"><span class="hljs-keyword">end</span></span>

pool(<span class="hljs-number">5</span>) { helper_method(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>) }</code></pre>

<p>C++ <a href="http://www.crystalclearsoftware.com/soc/coroutine/coroutine/coroutines.html">boost coroutines</a></p>



<pre class="prettyprint"><code class="language-c++ hljs ruby">typedef <span class="hljs-symbol">coro:</span><span class="hljs-symbol">:coroutine&lt;boost</span><span class="hljs-symbol">:</span><span class="hljs-symbol">:tuple&lt;int</span>, int&gt;(int)&gt; coroutine_type;

<span class="hljs-symbol">boost:</span><span class="hljs-symbol">:tuple&lt;int</span>, int&gt; muladd_body
  (<span class="hljs-symbol">coroutine_type:</span><span class="hljs-symbol">:self&amp;</span> <span class="hljs-keyword">self</span>, 
   int val) {
  int prod = <span class="hljs-number">0</span>;
  int sum = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">while</span>(<span class="hljs-keyword">true</span>) {
    prod += val;
    sum  += val;
    val = <span class="hljs-keyword">self</span>.<span class="hljs-keyword">yield</span>(<span class="hljs-symbol">boost:</span><span class="hljs-symbol">:make_tuple</span>(prod, sum));
  }
}

coroutine_type muladd(muladd_body);

template&lt;typename <span class="hljs-constant">ValueType</span>&gt;
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">generator</span> : <span class="hljs-title">public</span> <span class="hljs-title">std::iterator</span><span class="hljs-inheritance">&lt;<span class="hljs-parent">std::input_iterator_tag</span></span>, <span class="hljs-title">ValueType</span>&gt; {</span>
  typedef shared_coroutine&lt;<span class="hljs-constant">ValueType</span>()&gt; coroutine_type;
<span class="hljs-symbol">public:</span>
  typedef typename <span class="hljs-symbol">coroutine_type:</span><span class="hljs-symbol">:result_type</span> value_type;
  typedef typename <span class="hljs-symbol">coroutine_type:</span><span class="hljs-symbol">:self</span> <span class="hljs-keyword">self</span>;

  generator() {}

 generator(const generator&amp; rhs) <span class="hljs-symbol">:</span>
    m_coro(rhs.m_coro),
    m_val(rhs.m_val) {}

  template&lt;typename <span class="hljs-constant">Functor</span>&gt;
  generator(<span class="hljs-constant">Functor</span> f) <span class="hljs-symbol">:</span>
    m_coro(f), 
    m_val(assing()) {}

  value_type operator*() {
    <span class="hljs-keyword">return</span> *m_val;
  }

  generator&amp; operator++() {
    m_val = assing();
  }

  generator operator++(int) {
     generator t(*this);
     ++(*this);
     <span class="hljs-keyword">return</span> t;
  }

  friend operator==(const generator&amp; lhs, const generator&amp; rhs) {
    lhs.m_val == rhs.m_val;
  }
<span class="hljs-symbol">private:</span>
  <span class="hljs-symbol">boost:</span><span class="hljs-symbol">:optional&lt;vale_type&gt;</span> assign() {
    try {
      <span class="hljs-keyword">return</span> m_coro? m_coro() <span class="hljs-symbol">:</span>  <span class="hljs-symbol">boost:</span><span class="hljs-symbol">:optional&lt;value_type&gt;</span>();
    } catch (coroutine_exited) {
      <span class="hljs-keyword">return</span> <span class="hljs-symbol">boost:</span><span class="hljs-symbol">:optional&lt;value_type&gt;</span>()
    }
  }

  coroutine_type m_coro;
  <span class="hljs-symbol">boost:</span><span class="hljs-symbol">:optional&lt;value_type&gt;</span> m_val;
};</code></pre>



<h2 id="module">Module</h2>

<p>等同于 ECMASCript 2015</p>



<pre class="prettyprint"><code class="language-ts hljs coffeescript"><span class="hljs-reserved">import</span> * as fs from <span class="hljs-string">'fs'</span>

<span class="hljs-reserved">import</span> {readFile, writeFile} from <span class="hljs-string">'fs'</span>

<span class="hljs-reserved">import</span> {App} from <span class="hljs-string">'./app'</span>

<span class="hljs-reserved">export</span> <span class="hljs-reserved">var</span> a = <span class="hljs-number">1</span>

<span class="hljs-reserved">export</span> <span class="hljs-reserved">function</span> f() {

}

<span class="hljs-reserved">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">F</span> {</span>

}</code></pre>



<h2 id="更多">更多</h2>

<p>参考 <a href="http://www.typescriptlang.org/docs/index.html">TypeScript Docimentation</a></p>



<h2 id="编译-typescript-的三种方式">编译 TypeScript 的三种方式</h2>

<p>编译选项参考 <a href="http://www.typescriptlang.org/docs/handbook/compiler-options.html">Compiler Options</a></p>

<ol>
<li><p>CLI</p>

<pre class="prettyprint"><code class="language-sh hljs brainfuck"><span class="hljs-comment">tsc</span>  <span class="hljs-comment">src/test_generator</span><span class="hljs-string">.</span><span class="hljs-comment">ts</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">target</span> <span class="hljs-comment">ES6</span> 

<span class="hljs-comment">tsc</span>  <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">project</span> <span class="hljs-comment">src</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">target</span> <span class="hljs-comment">ES6</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">module</span> <span class="hljs-comment">commonjs</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">removeComments</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">jsx</span> <span class="hljs-comment">react</span></code></pre></li>
<li><p>使用 tsconfig.json</p>

<pre class="prettyprint"><code class="language-? hljs 1c">project
  <span class="hljs-string">|</span>
  <span class="hljs-string">|- tsconfig.json</span>
  <span class="hljs-string">|- src</span>
  <span class="hljs-string">|- dist</span>
  <span class="hljs-string">|- node_modules</span>
  <span class="hljs-string">|- docs</span></code></pre>

<pre class="prettyprint"><code class="language-json hljs ">{
  "<span class="hljs-attribute">compilerOptions</span>": <span class="hljs-value">{
    "<span class="hljs-attribute">module</span>": <span class="hljs-value"><span class="hljs-string">"commonjs"</span></span>,
    "<span class="hljs-attribute">removeComments</span>": <span class="hljs-value"><span class="hljs-literal">true</span></span>,
    "<span class="hljs-attribute">allowJs</span>": <span class="hljs-value"><span class="hljs-literal">true</span></span>,
    "<span class="hljs-attribute">experimentalDecorators</span>": <span class="hljs-value"><span class="hljs-literal">true</span></span>,
    "<span class="hljs-attribute">target</span>": <span class="hljs-value"><span class="hljs-string">"es6"</span></span>,
    "<span class="hljs-attribute">noImplicitAny</span>": <span class="hljs-value"><span class="hljs-literal">true</span></span>,
    "<span class="hljs-attribute">sourceMap</span>": <span class="hljs-value"><span class="hljs-literal">true</span></span>,
    "<span class="hljs-attribute">jsx</span>": <span class="hljs-value"><span class="hljs-string">"react"</span></span>,
    "<span class="hljs-attribute">rootDir</span>": <span class="hljs-value"><span class="hljs-string">"./src"</span></span>,
    "<span class="hljs-attribute">outDir</span>": <span class="hljs-value"><span class="hljs-string">"./dist"</span>
  </span>}</span>,
  "<span class="hljs-attribute">exclude</span>": <span class="hljs-value">[
    <span class="hljs-string">"node_modules"</span>, <span class="hljs-string">"docs"</span>
  ]
</span>}</code></pre>

<pre class="prettyprint"><code class="language-sh hljs cmake">tsc --<span class="hljs-keyword">project</span> .             <span class="hljs-comment"># project/</span></code></pre></li>
<li><p>使用 gulp</p>

<pre class="prettyprint"><code class="language-json hljs ">  <span class="hljs-string">"devDependencies"</span>: {
    "<span class="hljs-attribute">gulp</span>": <span class="hljs-value"><span class="hljs-string">"^3.9.1"</span></span>,
    "<span class="hljs-attribute">gulp-sourcemaps</span>": <span class="hljs-value"><span class="hljs-string">"^1.9.1"</span></span>,
    "<span class="hljs-attribute">gulp-typescript</span>": <span class="hljs-value"><span class="hljs-string">"^3.1.4"</span></span>,
    "<span class="hljs-attribute">typescript</span>": <span class="hljs-value"><span class="hljs-string">"^2.1.5"</span>
  </span>},</code></pre>

<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-keyword">var</span> gulp = <span class="hljs-built_in">require</span>(<span class="hljs-string">'gulp'</span>)
<span class="hljs-keyword">var</span> typescript = <span class="hljs-built_in">require</span>(<span class="hljs-string">'gulp-typescript'</span>)
<span class="hljs-keyword">var</span> sourcemaps = <span class="hljs-built_in">require</span>(<span class="hljs-string">'gulp-sourcemaps'</span>)
<span class="hljs-keyword">var</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>)
<span class="hljs-keyword">var</span> tsconfig = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./tsconfig.json'</span>) 

<span class="hljs-keyword">const</span> BASE_DIR = path.join(__dirname, <span class="hljs-string">'src'</span>)
<span class="hljs-keyword">const</span> DIST_DIR = <span class="hljs-string">'dist'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">compileMain</span><span class="hljs-params">(pathname)</span> {</span>
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> {</span>
    <span class="hljs-keyword">return</span> gulp
            .src(pathname, {
              base: BASE_DIR
            })
            .pipe(sourcemaps.init())
            .pipe(typescript(tsconfig.compilerOptions))
            .pipe(sourcemaps.write(<span class="hljs-string">'.'</span>))
            .pipe(gulp.dest(<span class="hljs-string">'dist'</span>))
  }
}

gulp.task(<span class="hljs-string">'build'</span>, compileMain(<span class="hljs-string">'src/**/*.ts'</span>))</code></pre>

<pre class="prettyprint"><code class="language-sh hljs ">gulp build</code></pre></li>
</ol>



<h1 id="webpack-介绍">WebPack 介绍</h1>

<p>WebPack 是一个最近开始流行的 Browser 模块化工具，把你所编写的 Browser JS 代码合并到一个文件，并自动赋予命名空间，使其具备模块化的功能。这样，你就可以编写模块化的 Browser JS 代码。</p>

<p>React 多数情况用于 Browser 的 HTML 渲染，所以我们这里使用 WebPack 组织 JS 代码。</p>

<p>更多的 WebPack 信息参考 <a href="https://webpack.github.io/">WebPack IO</a></p>

<blockquote>
  <p>WebPack 正在变的臃肿和反 JS 标准。WebPack 试图推出一个新的编程结构，但是又不制作新的编程语言，所有的编写都是用 JS 写的，但是却完全修改了 JS 标准（或者准标准）库的许多语义。如果你使用这些语义编写代码，多年之后，这些代码很容易导致：其他程序员看不懂，JS 标准不认可，业界不愿意支持（微软、Google 没有任何一个认为 WebPack 搞得这些东西可以成为一个标准）。</p>
  
  <p>最佳实践是只使用 WebPack 的打包工具，如同使用 Browserify，只用它的编译过程，其他的不要过问。这同时能甩开 WebPack 庞大臃肿的文档说明：只看你需要的内容，而且这部分内容很小。</p>
</blockquote>

<ul>
<li><p>target</p>

<p>WebPack 打包的时候有几种方式，<code>target</code> 指定目标环境。主要有 <code>web</code>、<code>nodejs</code>、<code>electron</code>、… <code>target</code> 不同，则打包时一些变量和包的导入规则也不同。</p></li>
<li><p>output</p>

<p>输出的目标文件路径</p></li>
<li><p>externals</p>

<p>有些引用的外部包，比如 <code>react</code>、<code>jquery</code>，不想要把它们一起打包进自己的代码（这样代码会很大，而且打包过程很慢）。<code>externals</code> 可以指定一个键值对，忽略打包的这些模块。</p></li>
<li><p>resolve</p>

<p>应该扫描那些格式的文件，进行打包。</p></li>
<li><p>module.loaders</p>

<p>这是 WebPack 提供的插件机制。loaders 可以提供各种不同语言的打包插件，比如 <code>js</code>、<code>css</code>、<code>ts</code> 等等。</p></li>
<li><p>…</p></li>
</ul>



<pre class="prettyprint"><code class="language-js hljs ">{
  target: <span class="hljs-string">'web'</span>,
  output: {
    filename: path.join(path.dirname(pathname).replace(<span class="hljs-regexp">/^\.?\/?src\/?/</span>, <span class="hljs-string">''</span>), path.basename(pathname, <span class="hljs-string">'.tsx'</span>) + <span class="hljs-string">'.js'</span>)
  },
  externals: [
    {
      <span class="hljs-string">'react'</span>: <span class="hljs-string">'React'</span>,
      <span class="hljs-string">'react-dom'</span>: <span class="hljs-string">'ReactDOM'</span>,
      <span class="hljs-string">'react-channel'</span>: <span class="hljs-string">'ReactChannel'</span>
    }
  ],
  resolve: {
    extensions: [<span class="hljs-string">''</span>, <span class="hljs-string">'.tsx'</span>],
  },
  devtool: <span class="hljs-string">'source-map'</span>,
  module: {
    loaders: [
      { 
        test: <span class="hljs-regexp">/\.tsx$/</span>, 
        loader: <span class="hljs-string">"ts-loader"</span>,
        exclude: <span class="hljs-regexp">/node_modules/</span>
      }
    ]
  }
}</code></pre>



<h1 id="typescript-react-webpack">TypeScript + React + WebPack</h1>



<h2 id="不使用-mvvm-的时代模板引擎">不使用 MVVM 的时代，模板引擎</h2>

<p>JavaScript 历史上存在很多模板引擎：ejs、hogan、mustache、…，这些模板引擎只做一个任务：把数据动态的渲染到字符串模板中，生成一个需要的字符串。这也说明，模板引擎是数据驱动的。</p>

<blockquote>
  <p>关于数据和解释器：</p>
  
  <p>有必要提前说明数据和解释器。</p>
  
  <p>Unix-like 风格的客户端和服务器之间传输数据，数据到达后，如何解释数据是两端自己的事情，双方只制定传输数据的内容格式和几个标识。这样的好处是可以面向数据编程，传输的数据以文本流表示，是人类可读的，使用压缩技术可以与二进制格式的性能相差无几。最重要的是，解耦了编程的两端。</p>
  
  <p>注意：这里提到的是 Unix-like 风格的服务器系统，而不是那些强调 RPC 把调用和数据绑定的古板的服务器系统。Unix 系统早期也原生提供一些 RPC，但是被认为是接口固化难以随时代发展变迁，后来又去掉了。但是，很明显，Java 领域出现了很多这样的服务器。</p>
</blockquote>

<p>由此可以大致描述一下模板引擎的工作过程：</p>



<pre class="prettyprint"><code class="language-? hljs css">                   <span class="hljs-attr_selector">[Data]</span>
<span class="hljs-attr_selector">[String Template]</span> <span class="hljs-tag">--------</span>&gt; <span class="hljs-tag">Engine</span> <span class="hljs-tag">--</span>&gt; <span class="hljs-attr_selector">[String Text]</span></code></pre>

<p>模板引擎不做 IO，只负责数据的产生，随后负责 IO 的调用把数据发送到目标（客户端）：</p>



<pre class="prettyprint"><code class="language-?      String Text hljs css"><span class="hljs-attr_selector">[writer]</span> <span class="hljs-tag">-------------</span>&gt; <span class="hljs-attr_selector">[client]</span></code></pre>

<p>ECMAScript 2015 标准原生提供了模板字符串的功能，在一定程序可以扮演模板引擎的角色： </p>



<pre class="prettyprint"><code class="language-js hljs "><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">renderTpl</span><span class="hljs-params">(items)</span> {</span>
  <span class="hljs-keyword">return</span> `
  &lt;h1&gt;User List&lt;<span class="hljs-regexp">/h1&gt;
  &lt;ul&gt;
    {
      items.map((item) =&gt; {
        return '&lt;li&gt;' + item.name + ':' + item.age + '&lt;/</span>li&gt;<span class="hljs-string">' 
      })
    }
  &lt;/ul&gt;
  `
}

var text = renderTpl([
  {
    name: '</span>XiaoMing<span class="hljs-string">',
    age: 31
  },
  {
    name: '</span>Tom<span class="hljs-string">',
    age: 21
  }
])</span></code></pre>

<p><code>renderTpl</code> 提供了一个数据接口 <code>items</code>，它是 <code>Array&lt;{name: string, value: number}&gt;</code> 结构。这段代码可以生成字符串:</p>



<pre class="prettyprint"><code class="language-html hljs ">
  <span class="hljs-tag">&lt;<span class="hljs-title">h1</span>&gt;</span>User List<span class="hljs-tag">&lt;/<span class="hljs-title">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">ul</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">li</span>&gt;</span>XiaoMing:31<span class="hljs-tag">&lt;/<span class="hljs-title">li</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">li</span>&gt;</span>Tom:21<span class="hljs-tag">&lt;/<span class="hljs-title">li</span>&gt;</span>  
  <span class="hljs-tag">&lt;/<span class="hljs-title">ul</span>&gt;</span>
</code></pre>

<p>然后，你可以使用 Node.js 的 IO 接口把这段数据发送到客户端：</p>



<pre class="prettyprint"><code class="language-js hljs ">res.write(<span class="hljs-number">200</span>, {<span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/html'</span>})
res.write(text)
res.end()</code></pre>

<p>模板引擎的好处是，可以数据驱动，符合数据编程的理念。随着客户端技术的需要，比如 ajax 动态数据切换、客户端交互，数据需要在客户端更新。每次更新，需要（手动）编程主动调用模板引擎渲染新的数据。</p>

<p>MVVM 是模板引擎的进一步实现，绑定了更新和数据渲染。在这种机制下，你需要指定数据和绑定的 DOM，不再需要主动调用更新代码。</p>



<h2 id="使用-react-的好处">使用 React 的好处</h2>

<p>React 是 Facebook 开源的 MVVM 数据绑定的渲染库，提供 HTML 的抽象表示</p>

<ul>
<li>使用抽象模块化的 VDOM 操作 HTML DOM Tree</li>
<li>各个 VDOM 以抽象组件的方式存在，利于扩展和维护</li>
<li>数据绑定，不需要额外的渲染操作</li>
</ul>



<h2 id="hello-rect">Hello Rect</h2>



<pre class="prettyprint"><code class="language-html hljs "><span class="hljs-doctype">&lt;!DOCTYPE html&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">meta</span> <span class="hljs-attribute">charset</span>=<span class="hljs-value">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">title</span>&gt;</span>Demo<span class="hljs-tag">&lt;/<span class="hljs-title">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">script</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"react.js"</span>&gt;</span><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-title">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">script</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"react-dom.js"</span>&gt;</span><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-title">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"wrapper"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">script</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">class</span> Message extends React.Component {
      render() {
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-title">div</span>&gt;</span>Hello {this.props.name}<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
      }
    }

    ReactDOM.render(<span class="hljs-tag">&lt;<span class="hljs-title">Message</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"John"</span> /&gt;</span>, document.getElementById('wrapper'))
  </span></span><span class="hljs-tag">&lt;/<span class="hljs-title">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">html</span>&gt;</span></code></pre>

<p><a href="https://facebook.github.io/react/">React docs</a></p>



<h2 id="例子">例子</h2>

<p><a href="http://git.oschina.net/tonyrobotics/learn01_typescript_webpack_react/tree/master/demo">source code</a></p>



<h2 id="react-lifecycle">React Lifecycle</h2>

<p><img src="https://raw.githubusercontent.com/crazycodeboy/RNStudyNotes/master/React%20Native%E4%B9%8BReact%E9%80%9F%E5%AD%A6%E6%95%99%E7%A8%8B/images/component-lifecycle.jpg" alt="React Lifecycle" title=""></p>

<ul>
<li><p>Mounting</p>

<ul><li><code>constructor()</code></li>
<li><code>componentWillMount()</code></li>
<li><code>render()</code></li>
<li><code>componentDidMount()</code></li></ul></li>
<li><p>Updating</p>

<ul><li><code>componentWillReceiveProps()</code></li>
<li><code>shouldComponentUpdate()</code></li>
<li><code>componentWillUpdate()</code></li>
<li><code>render()</code></li>
<li><code>componentDidUpdate()</code></li></ul></li>
<li><p>Unmounting</p>

<ul><li><code>componentWillUnmount()</code></li></ul></li>
</ul></div></body>
</html>